package com.conversationboard.api;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.SecurityContext;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.apache.lucene.queryParser.ParseException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.conversationboard.api.formatters.XmlDateFormatter;
import com.conversationboard.api.formatters.XmlWrapper;
import com.conversationboard.api.xml.ApiXPath;
import com.conversationboard.api.xml.XmlUtils;
import com.conversationboard.fulltext.search.Search;
import com.conversationboard.fulltext.search.SortOrder;
import com.conversationboard.fulltext.search.hit.ThreadHit;
import com.conversationboard.model.User;

/* For a thread search:
 * 
 * 		<Search>
 * 			<Offset>0</Offset>
 * 			<Responses>10</Responses>
 * 			<Type>ThreadTitle</Type>
 * 			<QueryString>[your query string]</QueryString>
 * 		</Search>
 * 
 * For a message search:
 * 
 * 		<Search>
 * 			<Offset>0</Offset>
 * 			<Responses>10</Responses>
 * 			<Type>Message</Type>
 * 			<QueryString>[your query string]</QueryString>
 * 		</Search>
 * 
 */

public class SearchProcessor implements Processor {

	private static XPathExpression queryStringExpression;
	private static XPathExpression typeExpression;
	private static XPathExpression offsetExpression;
	private static XPathExpression responsesExpression;

	static {
		try {
			queryStringExpression = ApiXPath.getXPath().compile("/Requests/Search/QueryString/text()");
			typeExpression = ApiXPath.getXPath().compile("/Requests/Search/Type/text()");
			offsetExpression = ApiXPath.getXPath().compile("/Requests/Search/Offset/text()");
			responsesExpression = ApiXPath.getXPath().compile("/Requests/Search/Responses/text()");
		} catch (XPathExpressionException e) {
		}
	}


	@Override
	public String processXml(String xml, SecurityContext securityContext, HttpServletRequest request) throws ApiException {

		Document document;
		StringBuilder responseXml = new StringBuilder();

		try {
			document = XmlUtils.getDocument(xml);

			String queryString = (String) queryStringExpression.evaluate(document, XPathConstants.STRING);
			String type = (String) typeExpression.evaluate(document, XPathConstants.STRING);
			int offset = Integer.parseInt((String) offsetExpression.evaluate(document, XPathConstants.STRING));
			int responses = Integer.parseInt((String) responsesExpression.evaluate(document, XPathConstants.STRING));

			User user = User.get(request.getUserPrincipal());

			if (type.equalsIgnoreCase("ThreadTitle")) {

				/* Thread title search */

				Search search = new Search();
				List<ThreadHit> hits = search.searchThreads(user, queryString, offset, responses, SortOrder.Relevance);

				responseXml.append("<Search><Results>");

				for (ThreadHit hit : hits) {
					responseXml.append("<Result>");
					responseXml.append("<BoardId>" + hit.getBoardId() + "</BoardId>");
					responseXml.append("<ThreadId>" + hit.getThreadId() + "</ThreadId>");
					responseXml.append(XmlWrapper.wrapCDATA("BoardName", hit.getBoardName()));
					responseXml.append(XmlWrapper.wrapCDATA("ThreadTitle", hit.getTitle()));
					responseXml.append(XmlWrapper.wrapCDATA("DisplayName", hit.getDisplayName()));
					responseXml.append("<CreationDate>" + XmlDateFormatter.format(hit.getTimestampAsDate()) + "</CreationDate>");
					responseXml.append("</Result>");
				}

				responseXml.append("</Results></Search>");
			}

		} catch (ParserConfigurationException e) {
			throw new ApiException(e);
		} catch (IOException e) {
			throw new ApiException(e);
		} catch (SAXException e) {
			throw new ApiException(e);
		} catch (XPathExpressionException e) {
			throw new ApiException(e);
		} catch (SQLException e) {
			throw new ApiException(e);
		} catch (ParseException e) {
			throw new ApiException(e);
		} catch (java.text.ParseException e) {
			throw new ApiException(e);
		}

		return responseXml.toString();
	}

}
